package edu.cicese.alz;

import org.openstreetmap.gui.jmapviewer.MapLine;
import org.openstreetmap.gui.jmapviewer.MapLocation;
import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.coordinates.LatLon;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.travelingsalesman.routing.IRouter;
import org.openstreetmap.travelingsalesman.routing.routers.MultiTargetDijkstraRouter;
import org.openstreetmap.travelingsalesman.routing.selectors.Motorcar;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 1/02/12
 * Time: 03:55 PM
 */
public class RouteUtils {

	private static int mapLocationCounter = 0;
	private static IRouter router = new MultiTargetDijkstraRouter();
//	private static IRouter router = new RoutingStepDistanceComparator();
	private static MemoryDataSet map;

	public static int getMapLocationCounter() {
		mapLocationCounter++;
		return mapLocationCounter;
	}

	public static List<URoute> findKnownRoutes(List<MapMarker> mapMarkers, List<MapLocation> mapLocations, List<MapLine> mapLines) {
		map = (new org.openstreetmap.osm.io.FileLoader(new File("D:\\_proyectoAlz\\misc\\ensenada.osm"))).parseOsm();

		ArrayList<URoute> uRoutes = new ArrayList<>();

		MapMarker m1 = null;
		for (MapMarker m2 : mapMarkers) {
			route(uRoutes, m1, m2);
			m1 = m2;
		}

		return uRoutes;

//		System.out.println(uRoutes.size() + " routes found.");
//		Color color = Color.GREEN;
//		try {
//			for (URoute uRoute : uRoutes) {
//				System.out.println("From " + uRoute.getStartLocationID() + " to " + uRoute.getEndLocationID());
//				for (Route.RoutingStep rs : uRoute.getRoute().getRoutingSteps()) {
//					mapLines.add(new MapLine(color, rs.getStartNode().getLatitude(), rs.getStartNode().getLongitude(),
//							rs.getEndNode().getLatitude(), rs.getEndNode().getLongitude()));
//				}
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		// do something with uRoutes
	}

	// TODO: getNearestNodes only once (performance issue).
	public static void route(ArrayList<URoute> routes, MapMarker m1, MapMarker m2) {
		LatLon targetCoord = new LatLon(m2.getLat(), m2.getLon());
		Node targetNode = map.getNearestNode(targetCoord, null);
		URoute uRoute;
		if (m1 != null) {
			LatLon startCoord = new LatLon(m1.getLat(), m1.getLon());
			Node startNode = map.getNearestNode(startCoord, null);
			switch (getStatus(m1, m2)) {
				case 0:
					routes.get(routes.size() - 1).addRoute(router.route(map, targetNode, startNode, new Motorcar()));
					break;
				case 1:
					uRoute = routes.get(routes.size() - 1);
					uRoute.addRoute(router.route(map, targetNode, startNode, new Motorcar()));
					uRoute.combine();
					uRoute.setEndLocationID(m2.getMapLocationID());
					break;
				case 2:
					uRoute = new URoute();
					uRoute.setStartNode(startNode);
					uRoute.addRoute(router.route(map, targetNode, startNode, new Motorcar()));
					uRoute.setStartLocationID(m1.getMapLocationID());
					routes.add(uRoute);
					break;
				case 3:
				case 4:
					// nothing...
					break;
			}
		}
		else if (!m2.isInLocation()) {
			uRoute = new URoute();
			uRoute.setStartNode(targetNode);
			routes.add(uRoute);
		}
	}

	public static int getStatus(MapMarker m1, MapMarker m2) {
		// null -> null  : 0 :  update route
		// null ->  l1   : 1 :  end route
		// 
		//  l1  -> null  : 2 :  start new route
		//  l1  ->  l1   : 3 :  -
		//  l1  ->  l2   : 4 :  -

		if (!m1.isInLocation()) {
			if (!m2.isInLocation()) {
				return 0;
			}
			else {
				return 1;
			}
		}
		else {
			if (!m2.isInLocation()) {
				return 2;
			}
			else if (m1.getMapLocationID() == m2.getMapLocationID()) {
				return 3;
			}
			else {
				return 4;
			}
		}
	}
}
